package org.snail.department.service.impl;

import lombok.extern.log4j.Log4j;
import org.apache.log4j.Logger;
import org.snail.common.dingding.utils.JedisUtils;
import org.snail.constant.CacheNameConstant;
import org.snail.constant.ErrCodeConstant;
import org.snail.dept.bean.DepartDO;
import org.snail.dept.bean.TreeNode;
import org.snail.dept.mapper.DepartmentMapper;
import org.snail.exception.CommonException;
import org.snail.exception.SqlException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * 部门服务类
 */
@Component
@Log4j
public class DepartmentTreeNodeService {
    private static final Logger LOGGER = Logger.getLogger(DepartmentTreeNodeService.class);

    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private JedisUtils jedisUtils;

    /**
     * 从缓存中获取部门树
     * @return
     * @throws SqlException
     * @throws CommonException
     */
    public TreeNode getTreeNode() throws SqlException, CommonException {
        TreeNode keysForValue = (TreeNode) jedisUtils.getKeysForValue(CacheNameConstant.TREENODE_CACHE);
        if (null == keysForValue) {
            keysForValue = getDepartmentTreeFromDB();
            if (null == keysForValue) {
                LOGGER.error("从redis获取部门树失败！");
                throw new CommonException(ErrCodeConstant.ILLEGAL_PARAM, "从redis获取部门树失败！");
            } else {
                jedisUtils.saveValue(CacheNameConstant.TREENODE_CACHE, keysForValue);
            }
        }
        return keysForValue;
    }

    /**
     * 从缓存中获取部门树
     * @return
     * @throws SqlException
     * @throws CommonException
     */
    public void delTreeNode()  {
        try {
            jedisUtils.deleteKey(CacheNameConstant.TREENODE_CACHE);
        } catch (CommonException e) {
            log.error("清除缓存中部门数据", e);
        }
    }

    /**
     * 获取部门树
     *
     * @return treeNode 最终生成的部门树
     */
    public TreeNode getDepartmentTreeFromDB(){
        TreeNode treeNode  = getDepartmentTreeFromDB("25393462", "BU9", "L2");
        return treeNode;
    }

    /**
     * 根据根部门ID获取部门树
     *
     * @param rootId   根部门id
     * @param rootName 部门名称
     * @param lv       部门层级 例 ：LV4
     * @return treeNode 最终生成的部门树
     */
    public TreeNode getDepartmentTreeFromDB(String rootId, String rootName, String lv) {
        TreeNode result = null;
        try {
            Map<String, TreeNode> treeMap = new HashMap<>();

            //获取所有部门
            Set<DepartDO> allDepartList = getTreeNodeList(Long.parseLong(rootId));
            log.info("allDepartList: " + allDepartList);
            //添加所有部门
            treeMap.putAll(generateDepartmentMap(allDepartList));
            log.info("treeMap: " + treeMap);

            //生成root节点
            TreeNode rootTreeNode = new TreeNode();
            rootTreeNode.setId(rootId);
            rootTreeNode.setName(rootName);
            rootTreeNode.setLv(lv);
            //添加根部门
            treeMap.put(rootId, rootTreeNode);

            //生成树
            generateTree(treeMap);
            log.info("treeMap.get(rootId): " + treeMap.get(rootId));
            //生成LV层级
            TreeNode treeNode = generateTreeLv(treeMap.get(rootId), 10);
            log.info("treeNode: " + treeNode);

            result = treeNode;
        } catch (Exception e) {
            LOGGER.error("钉钉接口：获取部门树失败！", e);
        }
        return result;
    }

    /**
     * 生成部门Map
     *
     * @param allDepartList 部门列表
     * @return map key 部门id， value 针对该部门的树
     */
    public Map<String, TreeNode> generateDepartmentMap(Set<DepartDO> allDepartList) throws Exception {
        Map<String, TreeNode> treeMap = new HashMap<>();
        if(null!=allDepartList && !allDepartList.isEmpty()) {
            for (DepartDO departDO : allDepartList) {
                if (null != departDO) {
                    TreeNode oneTreeNode = new TreeNode();
                    oneTreeNode.setId(departDO.getId() + "");
                    oneTreeNode.setName(departDO.getName());
                    oneTreeNode.setParentId(departDO.getParentid() + "");

                    //获取部门管理者
                    List<String> groupManagerList = getDepartmentManagerIDList(departDO.getManagers());
                    oneTreeNode.setManager(groupManagerList);

                    //获取数据库部门人员信息
                    List<String> userIdList = departmentMapper.findUserIdListByDeptId(departDO.getId());
                    oneTreeNode.setUserList(userIdList);

                    treeMap.put(departDO.getId() + "", oneTreeNode);
                }
            }
        }
        return treeMap;
    }

    /**
     * 格式化部门管理员
     *
     * @param managerUsers 将人员列表字符串转化List
     * @return groupManagerList list格式
     */
    private static List<String> getDepartmentManagerIDList(String managerUsers) {
        List<String> groupManagerList = new ArrayList<>();
        if (!StringUtils.isEmpty(managerUsers)) {
            String[] managerArray = managerUsers.split("\\|");
            for (int j = 0; j < managerArray.length; j++) {
                String oneManagerStr = managerArray[j];
                if (!StringUtils.isEmpty(oneManagerStr)) {
                    groupManagerList.add(oneManagerStr);
                }
            }
        }
        return groupManagerList;
    }

    /**
     * 生成树
     *
     * @param nodeMap
     * @param <T>
     * @throws Exception
     */
    private static <T extends TreeNode> void generateTree(Map<String, T> nodeMap) throws Exception {
        // 建立父子关系
        for (TreeNode node : nodeMap.values()) {
            String parentId = node.getParentId();

            if (node.isRoot(parentId)) {
                continue;
            }
            log.info("parentId : " + parentId);
            if (nodeMap.containsKey(parentId)) {

                TreeNode parentNode = nodeMap.get(parentId);
                if (parentNode == null) {
                    throw new Exception("生成树失败");
                } else {
                    log.info("parentNode : " + parentNode + ", node : " + node);
                    parentNode.addChildNode(node);
                    node.setParentNode(parentNode);
                }
            }
        }
    }

    /**
     * 生成LV层级
     *
     * @param treeNode 最高层级的treenode
     * @param topDep   最多循环的次数，防止栈溢出
     */
    private static TreeNode generateTreeLv(TreeNode treeNode, int topDep) {
        if (null != treeNode && topDep >= 0) {
            topDep--;
            List<TreeNode> list = treeNode.getChildren();
            String lv = treeNode.getLv();
            if (null != list && list.size() > 0) {
                for (TreeNode oneTreeNode : list) {
                    oneTreeNode.setLv(generateNextLv(lv));
                    generateTreeLv(oneTreeNode, topDep);
                }
            }
        }
        return treeNode;
    }

    /**
     * lv 增长
     *
     * @param lv 部门层级
     * @return String 显示下一层及
     */
    private static String generateNextLv(String lv) {
        String nextLv = null;
        if (!StringUtils.isEmpty(lv)) {
            nextLv = lv.substring(0, 1) + (char) (lv.charAt(1) + 1);
        }
        return nextLv;
    }

    /**
     * 根据部门名称去获取所有子节点部门
     *
     * @param
     * @return
     */
    public Set<DepartDO> getTreeNodeList(Long deptId) {
        Set<DepartDO> departHashSet = new HashSet<>();
        generateTreeList(departHashSet, deptId);
        return departHashSet;
    }

    /**
     * 获取下级部门信息，添加到集合中
     * @param departHashSet
     * @param departmentId
     */
    private void generateTreeList(Set<DepartDO> departHashSet, Long departmentId) {
        if(null==departHashSet) {
            departHashSet = new HashSet<DepartDO>();
        }

        DepartDO departDO = departmentMapper.findDeptByDepartmentId(departmentId);
        if (null != departDO) {
            departHashSet.add(departDO);
            List<DepartDO> departDOS = departmentMapper.findDeptByParentId(departDO.getId());
            for (DepartDO dept : departDOS) {
                generateTreeList(departHashSet, dept.getId());
            }
        }
    }

    /**
     * 根据部门名称找部门
     * @param deptName
     * @return
     */
    public List<DepartDO> getDeptInfoByName(String deptName) {
        return departmentMapper.findDeptInfoByName(deptName);
    }

    /**
     *  查找部门成员信息
     * @return
     */
    public Map<Object, Object> selectDeptByEmployeeId() {
        Map<Object, Object> employeDeptMap = new HashMap<>();
        List<Map<String, Object>> employeDepts = departmentMapper.findDeptByEmployeeId();
        for (Map<String,Object> employeDept : employeDepts)
            if (employeDept != null) {
                Object empId= employeDept.get("id");
                Object deptName = employeDept.get("name");
                if (empId != null && deptName != null) {
                    employeDeptMap.put(empId, deptName);
                }
            }
        return employeDeptMap;
    }

}
